#ifndef     __CMD_UART_H
#define     __CMD_UART_H

#include "../utils/codec.h"
#include "../rtos/message_queue.h"
#include "../utils/byte_view_t.h"
#include "../utils/object.h"
#include "../utils/no_copyable.h"

namespace driver {

class CmdUart : utils::no_copyable_t {

public:
    static constexpr uint32_t RecvBuffSize = 128;
    static constexpr uint32_t WriteBuffSize = 64;

    CmdUart();

    template <typename... Ts>
    void write(uint16_t req, Ts&&... ts) {
        wait_write_complete();
        uint32_t len = utils::make_proto(m_write_buf, req, std::forward<Ts>(ts)...);
        write_by_dma(m_write_buf, len);
    }

    void throw_log(uint8_t ec, const char *fmt, ...);

    inline osStatus_t poll(utils::byte_view_t &bw, uint32_t timeout = osWaitForever) {
        return m_mq.poll(bw, timeout);
    }

    void on_recv_idle();

private:
    static void wait_write_complete();
    static void write_by_dma(const void *buf, uint32_t len);

    uint8_t m_recv_buf[RecvBuffSize];
    uint8_t m_copy_buf[RecvBuffSize];
    uint8_t m_write_buf[WriteBuffSize];
    uint32_t m_recv_index;

    rtos::MessageQueue<utils::byte_view_t, 10> m_mq;
};

inline utils::object_t<CmdUart> cmdUart;

}


#endif
